home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / extensions / samples / ConvSharpenBlur.c next >
C/C++ Source or Header  |  1996-11-11  |  9KB  |  324 lines

  1. /*
  2.  * Copyright (c) 1994 Silicon Graphics, Inc.
  3.  * 
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee,
  6.  * provided that (i) the above copyright notices and this permission
  7.  * notice appear in all copies of the software and related documentation,
  8.  * and (ii) the name of Silicon Graphics may not be used in any
  9.  * advertising or publicity relating to the software without the specific,
  10.  * prior written permission of Silicon Graphics.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  15.  * 
  16.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
  17.  * INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
  18.  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  19.  * OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
  20.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  21.  * OF THIS SOFTWARE.
  22.  */
  23.  
  24. /*
  25.  * ConvSharpenBlur - Demonstrate sharpenening and bluring of an image using
  26.  *  convolution.
  27.  * 
  28.  * Keys:
  29.  *    Home - Set sharpness to 0 (neutral)
  30.  *    Up/Down - increase/decrease sharpness by 0.25
  31.  *    s - toggle histogram display
  32.  *    m - print min max value.
  33.  *    i - print sharpness value
  34.  *    x/y - toggle x/y mirroring of image
  35.  *    h/? - help
  36.  *    Esc - quit
  37.  */
  38. #include <stdlib.h>
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <GL/glx.h>
  42. #include <X11/keysym.h>
  43. #include "xwindow.h"
  44.  
  45. #define RECT_SIZE 512
  46. #define WIN_SIZE 1.5*RECT_SIZE
  47. #define XORG 0.25*RECT_SIZE
  48. #define YORG 0.25*RECT_SIZE
  49.  
  50. GLubyte buf1[RECT_SIZE][RECT_SIZE][3];
  51.  
  52. static float sharpness = 0;
  53.  
  54. static GLboolean doHistogram = GL_FALSE;
  55.  
  56. GLint curPos[2] = {XORG, YORG};
  57. Display *dpy;
  58. Window win;
  59. GLint xFlip = 1, yFlip = 1;
  60.  
  61. void render(void);
  62. void getMinMax(void);
  63.  
  64. #if defined(GL_EXT_convolution) && defined(GL_EXT_histogram)
  65.  
  66. void
  67. main(int argc, char* argv[])
  68. {
  69.     int visualAttr[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 1, None};
  70.     GLboolean done = GL_FALSE;
  71.     GLXContext ctx;
  72.     int yi, xi;
  73.     const GLubyte *extensionsString;
  74.  
  75.     if (argc > 1) {
  76.         fprintf(stderr, "usage: %s [-h for help]\n", argv[0]);
  77.         fprintf(stderr,
  78.                 "\tInteractively, `h/?' keys provide description of\
  79.  interface\n");
  80.         exit (argv[1][0] == '-' && argv[1][1] == 'h' ?
  81.               EXIT_SUCCESS : EXIT_FAILURE);
  82.     }
  83.         
  84.  
  85.     createWindowAndContext(&dpy, &win, &ctx, 100, 100, WIN_SIZE, WIN_SIZE,
  86.                            GL_TRUE, NULL, visualAttr, "Convolve");
  87.     extensionsString = glGetString(GL_EXTENSIONS);
  88.     /*
  89.      * Check for convolution extension.
  90.      */
  91.     if (extensionsString == NULL ||
  92.         !strstr((const char *) extensionsString, "EXT_convolution")) {
  93.         /*
  94.          * HACK - Convolution is not formally advertised.  Try using it anyhow.
  95.          */
  96.         glDisable(GL_CONVOLUTION_2D_EXT);
  97.         if (glGetError() != GL_NO_ERROR) {
  98.             fprintf(stderr, "Sorry convolution is not supported by the renderer\n");
  99.             exit(EXIT_FAILURE);
  100.         } else
  101.             fprintf(stderr, "Assuming EXT_convolution supported but not\
  102.  advertised\n");
  103.     }
  104.     /*
  105.      * Check for histogram extension.
  106.      */
  107.     if (!strstr((const char *) extensionsString, "EXT_histogram")) {
  108.         /*
  109.          * HACK - Histogram is not formally advertised.  Try getting it anyhow.
  110.          */
  111.         glDisable(GL_HISTOGRAM_EXT);
  112.         if (glGetError() != GL_NO_ERROR) {
  113.             fprintf(stderr, "Sorry histogram is not supported in the renderer\n");
  114.             exit(EXIT_FAILURE);
  115.         } else
  116.             fprintf(stderr, "Assuming EXT_histogram supported but not\
  117.  advertised\n");
  118.     }
  119.     /* Create Image */
  120.     for (yi = 0; yi < RECT_SIZE; yi++)
  121.         for (xi = 0; xi < RECT_SIZE; xi++) {
  122.             buf1[yi][xi][0] = xi & 0xff;
  123.             buf1[yi][xi][1] = (xi^yi) & 0xff;
  124.             buf1[yi][xi][2] = yi & 0xff;
  125.         }
  126.  
  127.  
  128.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  129.     glPixelStorei(GL_UNPACK_ROW_LENGTH, RECT_SIZE);
  130.     glViewport(0, 0, WIN_SIZE, WIN_SIZE);
  131.     glLoadIdentity();
  132.     glOrtho(0, WIN_SIZE, 0, WIN_SIZE, -1, 1);
  133.  
  134.     glClearColor(0.1, 0.4, 0.8, 0.);
  135.  
  136.     /*
  137.      * Select histogram and minmax statistic to RGBA (even though we're only
  138.      * going to read RGB).  As they are not used together both are "sink"ed
  139.      * (no drawing to frame buffer).  If histogram and minmax were used
  140.      * together, then we would only sink minmax (comes last).
  141.      */
  142.     glMinmaxEXT(GL_MINMAX_EXT, GL_RGBA, GL_TRUE);
  143.     glHistogramEXT(GL_HISTOGRAM_EXT, 4096, GL_RGBA, GL_TRUE);
  144.  
  145.     while (!done) {
  146.         XEvent event;
  147.  
  148.         XNextEvent(dpy, &event);
  149.         switch (event.type) {
  150.           case KeyPress:
  151.             switch (XLookupKeysym(&event.xkey, 0)) {
  152.               case XK_Escape:
  153.                 done = GL_TRUE;
  154.                 break;
  155.               case XK_i:
  156.               case XK_I:
  157.                 printf("Sharpeness is %g\n",sharpness);
  158.                 break;
  159.               case XK_m:
  160.                 getMinMax();
  161.                 break;
  162.           case XK_s:
  163.         doHistogram = !doHistogram;
  164.         printf("Histogram is %s\n", doHistogram ? "ON" : "OFF");
  165.         render();
  166.         break;
  167.               case XK_x:
  168.                 xFlip *= -1;
  169.                 curPos[0] -= RECT_SIZE * xFlip;
  170.                 render();
  171.                 break;
  172.               case XK_y:
  173.                 yFlip *= -1;
  174.                 curPos[1] -= RECT_SIZE * yFlip;
  175.                 render();
  176.                 break;
  177.           case XK_Up:
  178.         if (sharpness < 10) {
  179.             sharpness += 0.25;
  180.             render();
  181.         }
  182.         break;
  183.           case XK_Home:
  184.         sharpness = 0;
  185.         render();
  186.         break;
  187.           case XK_Down:
  188.         if (sharpness > -10) {
  189.             sharpness -= 0.25;
  190.             render();
  191.         }
  192.         break;
  193.           case XK_h:
  194.           case XK_H:
  195.           case XK_question:
  196.         printf("Keys:\tHome - Set sharpness to 0 (neutral)\n");
  197.         printf("\tUp/Down - increase/decrease sharpness\n");
  198.         printf("\ts - toggle histogram display\n");
  199.         printf("\tm - print min max value.\n");
  200.         printf("\ti - print sharpness value\n");
  201.         printf("\tx/y - toggle x/y mirroring of image\n");
  202.         printf("\th/? - help\n");
  203.         printf("\tEsc - quit\n");
  204.         break;
  205.             }
  206.                 break;
  207.           case DestroyNotify:
  208.             done = GL_TRUE;
  209.             break;
  210.           case Expose:
  211.             render();
  212.             break;
  213.         }
  214.     }
  215. }
  216.  
  217. /*
  218.  * Define the convolution filter.
  219.  *   0 means no filtering.
  220.  *   Positive/Negative mean sharpen/blur.
  221.  *   When filtering, a separable radially symetric 5x5 kernel is used.
  222.  */
  223. void
  224. setFilter(float sharpness    /* [-10..10] */)
  225. {
  226.     float row[5];
  227.     float k0, k1, kscale;
  228.     if (sharpness != 0.0) {
  229.         if (sharpness < 0.0) {
  230.             k0 = 0.15 - sharpness * 0.285;
  231.             k1 = -0.6 - sharpness * 0.360;
  232.         } else {
  233.             k0 = 0.15 - sharpness * 0.045;
  234.             k1 = -0.6 - sharpness * 0.045;
  235.         }
  236.  
  237.         kscale = 1/(2*k0 + 2*k1 + 3);
  238.         row[0] = row[4] = k0 * kscale;
  239.         row[1] = row[3] = k1 * kscale;
  240.         row[2] = 3 * kscale;
  241.     glSeparableFilter2DEXT(GL_SEPARABLE_2D_EXT, GL_LUMINANCE,
  242.                                5, 5, GL_LUMINANCE, GL_FLOAT, row, row);
  243.     glEnable(GL_SEPARABLE_2D_EXT);
  244.     } else
  245.     glDisable(GL_SEPARABLE_2D_EXT);
  246. }
  247.  
  248. /*
  249.  * Retrieve and print the image min and max component values.
  250.  */
  251. void
  252. getMinMax()
  253. {
  254.     GLfloat minmax[6];
  255.  
  256.     glEnable(GL_MINMAX_EXT);
  257.     glResetMinmaxEXT(GL_MINMAX_EXT);
  258.     glReadBuffer(GL_FRONT);
  259.     glCopyPixels(XORG, YORG, RECT_SIZE, RECT_SIZE, GL_COLOR);
  260.     glReadBuffer(GL_BACK);
  261.     glGetMinmaxEXT(GL_MINMAX_EXT, GL_TRUE, /* Reset */
  262.                    GL_RGB, GL_FLOAT, minmax);
  263.     printf("Min (%g %g %g) Max (%g %g %g)\n",
  264.            minmax[0], minmax[1], minmax[2],
  265.            minmax[3], minmax[4], minmax[5]);
  266.     glDisable(GL_MINMAX_EXT);
  267. }
  268.  
  269. /*
  270.  * Retrieve and draw the image histogram.
  271.  */
  272. void
  273. getHistogram(void)
  274. {
  275.     GLfloat hist[3*4096], *histp;
  276.     static const float colors[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
  277.     int i,j;
  278.  
  279.     glDisable(GL_SEPARABLE_2D_EXT);
  280.     glEnable(GL_HISTOGRAM_EXT);
  281.     glResetHistogramEXT(GL_HISTOGRAM_EXT);
  282.     glCopyPixels(XORG, YORG, RECT_SIZE, RECT_SIZE, GL_COLOR);
  283.     glGetHistogramEXT(GL_HISTOGRAM_EXT, GL_TRUE, /* reset */
  284.                       GL_RGB, GL_FLOAT, hist);
  285.     glDisable(GL_HISTOGRAM_EXT);
  286.     for (j = 0; j < 3; j++)  {
  287.     glColor3fv(&colors[3*j]);
  288.     histp = &hist[j];
  289.     glBegin(GL_LINE_STRIP);
  290.     for (i = 0; i < 4096; i++, histp += 3) {
  291.         glVertex2f(10 + i * ((GLfloat) WIN_SIZE - 20)/4096,
  292.                50 + (WIN_SIZE - 100)/3.0 * (j  +
  293.                        50**histp/(RECT_SIZE*RECT_SIZE)));
  294.     }
  295.     glEnd();
  296.     }
  297. }
  298.  
  299. /*
  300.  * Render a single frame.
  301.  */
  302. void
  303. render()
  304. {
  305.     glClear(GL_COLOR_BUFFER_BIT);
  306.  
  307.     glDisable(GL_SEPARABLE_2D_EXT);
  308.     glPixelZoom(1, 1);
  309.     glRasterPos2i(XORG, YORG);
  310.     glDrawPixels(RECT_SIZE, RECT_SIZE, GL_RGB, GL_UNSIGNED_BYTE, buf1);
  311.  
  312.     glPixelZoom(xFlip, yFlip);
  313.     glRasterPos2iv(curPos);
  314.     setFilter(sharpness);
  315.     glCopyPixels(XORG, YORG, RECT_SIZE, RECT_SIZE, GL_COLOR);
  316.     if (doHistogram)
  317.     getHistogram();
  318.     glXSwapBuffers(dpy, win);
  319. }
  320. #else  /* either histogram on convolution is not part of the library */
  321. /* Generate a compiler error with a message */
  322. Sorry CONVOLUTION OR HISTOGRAM is not supported by the library.
  323. #endif
  324.